package com.dmj.sqldsl.builder;

import static java.util.stream.Collectors.toList;

import com.dmj.sqldsl.builder.column.ColumnBuilder;
import com.dmj.sqldsl.builder.column.type.ColumnLambda;
import com.dmj.sqldsl.builder.config.EntityConfig;
import com.dmj.sqldsl.model.DslInsert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class InsertConflictBuilder<T, R> {

  private final InsertValuesBuilder<T> insertValuesBuilder;

  private final List<ColumnBuilder<T, R>> conflictColumnBuilders;

  private List<ColumnBuilder<T, R>> returningColumnBuilders;

  private UpdateBuilder<T> updateBuilder;

  protected InsertConflictBuilder(InsertValuesBuilder<T> insertValuesBuilder,
      List<ColumnBuilder<T, R>> conflictColumnBuilders) {
    this.insertValuesBuilder = insertValuesBuilder;
    this.conflictColumnBuilders = conflictColumnBuilders;
    this.returningColumnBuilders = new ArrayList<>(0);
  }

  public InsertFinishBuilder<T, R> doNoting() {
    return new InsertFinishBuilder<>(this);
  }

  @SafeVarargs
  public final InsertFinishBuilder<T, R> returning(ColumnLambda<T, R>... columnLambdas) {
    this.returningColumnBuilders = Arrays.stream(columnLambdas)
        .map(ColumnLambda::getColumnBuilder).collect(toList());
    return new InsertFinishBuilder<>(this);
  }

  public InsertFinishBuilder<T, R> doUpdate(UpdateBuilder<T> updateBuilder) {
    this.updateBuilder = updateBuilder;
    return new InsertFinishBuilder<>(this);
  }

  protected DslInsert toInsert(EntityConfig config) {
    DslInsert insert = insertValuesBuilder.toInsert(config);
    insert.setConflictColumns(
        conflictColumnBuilders.stream().map(x -> x.build(config)).collect(Collectors.toList()));
    insert.setReturningColumns(
        returningColumnBuilders.stream().map(x -> x.build(config)).collect(Collectors.toList()));
    insert.setUpdate(updateBuilder.toUpdate(config));
    return insert;
  }
}
